#ifndef PERMUTATION_H
#define PERMUTATION_H
#include <vector>
#include <string>
#include "XmlDefinitions.h"
#include "./Markup/Markup.h"

using std::vector;
using std::string;

class Permutation; 

class RelatedPermutation
{
public:
	RelatedPermutation(int groupIndex, int intersection): m_GroupIndex(groupIndex), m_Intersection(intersection){};
	int GetIndex() const { return m_GroupIndex; };
	int GetIntersection() const { return m_Intersection; };
	bool operator== (const RelatedPermutation &other) const;
	bool operator!= (const RelatedPermutation &other) const;
	void Save(CMarkup &xml);


private:
	int m_Intersection;
	int m_GroupIndex;
};

class Permutation
{
public:
	Permutation(unsigned long *permutationList,int wordLen, int groupSize);
	Permutation(unsigned long *permutationList,int wordLen, int groupSize, int name);
	~Permutation(void);
	int Permutation::CountIntersection(unsigned long* groupB, int groupBrows);
	unsigned long *GetMatrixColumns() const;
	unsigned long *GetMatrixRows() const;
	void UpdateMatrix(unsigned long* newPerm, int newGroupSize);
	int GetGroupSize() const; 
	static unsigned long* GetMatrixWithoutIntersection(unsigned long* matrixToClean, int matrixToCleanRows, unsigned long* otherMatrix, int otherMatrixRows, int intersectionSize);
	Permutation *NextPermutation();
	bool operator== (const Permutation &other) const;
	bool operator!= (const Permutation &other) const;
	void AddRelatedPerm(RelatedPermutation other);
	vector<RelatedPermutation>::iterator GetRelatedPermsBegin() { return m_RelatedPerms.begin();};
	vector<RelatedPermutation>::iterator GetRelatedPermsEnd() { return m_RelatedPerms.end();};
	int GetRelatedPermsCount() {return m_RelatedPerms.size();};
	Permutation *Clone() const;
	void SetName(const int name) {m_GroupIndex=name; };
	int GetName() const { return m_GroupIndex; };
	void SaveToXml(CMarkup &xml) const;
	void SaveRelatedPermsToXml(CMarkup &xml);


private:
	int m_WordLen; // How long is each binary word - column count
	int m_GroupSize; // How many words are in group
	unsigned long *m_Permutation; // List of unsigned longs that are the binary words (the matrix rowes)
	vector<RelatedPermutation> m_RelatedPerms;
	int m_GroupIndex;

	unsigned long* TransposeMatrixBits(const int rowCount, const int colCount) const;
	string GetVertexNameString(unsigned long vertex) const;
	static int CleanPermutation(unsigned long *perm, int size); // Removes duplicates
};

#endif
